package com.b1.taskmanagerclient.connect;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 * Класс потоковой работы клиента.
 * обеспечивает взаимодействие программы клиента и сервера. 
 * @author Exoo
 */

public class Client implements Runnable
{
    private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(Client.class);
    private Socket socket;              // сокет подключения
    private String [][] taskList;       // массив задач
    private String [][] contactList;    // массив контактов
    private ObjectOutputStream out;     // исходящий поток
    private ObjectInputStream in;       // входящий поток
    private boolean connect = false;    // переменная установления подключения
    private Thread requestThread;       // поток запросов для получения наступившей задачи или обновления данных клиента

    /**
     * метод получения значения переменной утановлено ли подключение
     * @return 
     */
    public boolean isConntect() {
        return connect;
    }
    
    /**
     * Конструктор класса
     * инициализирует сокет подключения
     * устанавливает исходящий и входящие потоки
     * @param host
     * @param port
     * @throws UnknownHostException
     * @throws IOException 
     */
    
    public Client(String host, int port) throws UnknownHostException, IOException
    {
        socket = new Socket(host,port);
        out = new ObjectOutputStream(socket.getOutputStream());
        in = new ObjectInputStream(socket.getInputStream());
    }

    /**
     * метод получения массива контактов
     * @return  String[length][3]
     */
    public String[][] getContactList() {
        return contactList;
    }
    
    /**
     * метод присваения нового контак листа и отправки обновленного массива на сервер
     * @param contactList 
     */
    public void setContactList(String[][] contactList) {
        this.contactList = contactList;
        try 
        {
            sendDate(contactList,3);
            log.info("Send contactList");
        }
        catch (InterruptedException ex) 
        {
            log.error(Client.class.getName(),ex);
        }
        catch (IOException ex) 
        {
            log.error(Client.class.getName(),ex);
        }
    }

    /**
     * метод получения массива задач
     * @return  String[length][8]
     */
    public String[][] getTaskList() {
        return taskList;
    }

    /**
     * метод присваения нового массива задач и отправки его на сервер
     * @param taskList
     */
    public void setTaskList(String[][] taskList) {
        this.taskList = taskList;
        try {
            sendDate(taskList,2);
            log.info("Send task List");
        }
        catch (InterruptedException ex) {
            log.error(Client.class.getName(),ex);
        }
        catch (IOException ex) {
            log.error(Client.class.getName(),ex);
        }
    }
    /**
     * потоковый метод работы клиента
     * получает данные от сервера и запускает Daemon поток
     * перезапросов для обновления на сервер
     */
    @Override
    public void run()
    {
        try 
        {
            getData();
            log.info("Start client");
            requestThread = new Thread(new Request());
            requestThread.setDaemon(true);
            requestThread.start();
            connect = true;            
        } 
        catch (ClassNotFoundException ex) {
            log.error(Client.class.getName(),ex);
        } 
        catch (IOException ex) {
            log.error(Client.class.getName(),ex);
        }
    }
    /**
     * метод отправки данных на сервер
     * @param data
     * @param id = 2 - отправка массива задач
     * @param id = 3 - отправка массива контактов
     * @throws IOException
     * @throws InterruptedException 
     */
    private void sendDate(String[][] data, int id) throws IOException,InterruptedException
    {
        if ((id > 3) && (id < 2)) 
        {
            log.warn("Uncknown id data");
            return;
        }
        requestThread.sleep(1000);
        out.writeObject(id);
        out.flush();
        out.writeObject(data);
        out.flush();
    }
    
    /**
     * метод получения данных от сервера
     * @throws IOException
     * @throws ClassNotFoundException 
     */
    private void getData() throws IOException, ClassNotFoundException
    {
        Object obj;
        out.writeObject(0);     //запрос на полчучение списка задач
        out.flush();
        obj = in.readObject();
        taskList = new String[3][8];
        if (obj.toString().equals("ok")) 
        {
            obj = in.readObject();
            taskList = (String[][]) obj;
        }
        out.writeObject(1);     //запрос на полчучение списка контактов
        out.flush();
        obj = in.readObject();
        contactList = new String[2][3];
        if (obj.toString().equals("ok")) 
        {
            obj = in.readObject();
            contactList = (String[][]) obj;
        }
    }
    
    /**
     * класс перезапросов на сервер
     * для полчения наступившего события или для обновления данных у клиента
     */
    private class Request implements Runnable    
    {
        /**
         * потоковый метод класса
         * обеспечивает постоянные запросы на сервер
         * для получения новых данных или сообщения наступившей задачи
         */
        public void run()
        {
            while(true)
            {
                try {
                    Thread.sleep(100);
                    Object obj;
                    out.writeObject(4);     // запрос на получение данных
                    out.flush();
                    obj = in.readObject();
                    if (obj.equals("new"))
                    {
                        taskList = (String[][])in.readObject();
                        contactList = (String[][])in.readObject();
                        continue;
                    }
                    out.writeObject(5);     // запрос о наступившей задаче
                    out.flush();
                    obj = in.readObject();
                    if (obj.equals("ok"))
                    {
                        obj = in.readObject();
                        JOptionPane.showMessageDialog(null,obj.toString(), "Came Event", JOptionPane.PLAIN_MESSAGE);
                        continue;
                    }
                } 
                catch (InterruptedException ex) {
                     log.error(Client.class.getName(),ex);
                } 
                catch (ClassNotFoundException ex) {
                    log.error(Client.class.getName(),ex);
                } 
                catch (IOException ex) {
                    log.error(Client.class.getName(),ex);
                }
            }
        }
    }
}
